package my.support;

import my.Interfaces.Savable;
import my.vo.Vo;

import java.io.*;
import java.util.List;

/**
 * @author 星环
 * @date 2022/11/2 14:24:14
 * @description  用于管理实体的存储与读取，参数是Vo的子类，实现Closeable是否可以try时自动关闭呢，反正也用不上。。
 */
public class VoIODealer<T extends Vo>  implements Closeable {
    //读取文件的流
    private  FileReader fileReader;
    //包装以使用readLine
    private  BufferedReader bufferedReader;
    //文件写入用，因为可以写入String，每条数据也是String，正好
    private  FileWriter  fileWriter;
    //因为不能同时开输入输出流，每次用完流就得关，所以把存储位置存个file在这
    private File file;
    //如果要读取idCounter的值，可以再加，但是懒得加了，直接for计算吧

    /**
     * 指定操作文件的路径
     * @param filePath 文件路径
     */
    public VoIODealer(String filePath){
        file = new File(filePath);
        try {
            if(!file.exists()) {
                file.createNewFile();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 从{@code file} 中读取信息到list中，每个空对象由{@link Vo}的{@code getEmptyInstance()}创建<br/>
     * 类似原型模式和桥接模式？
     * @param list 要读取信息的list
     * @param voPrototype 获取空对象的引子
     */
    public void read(List<T> list,T voPrototype) {
        //打开流
        try {
            fileReader = new FileReader(file);
            bufferedReader = new BufferedReader(fileReader);
        }catch (Exception e){
            e.printStackTrace();
        }
        //因为子类重写了Vo的getEmptyInstance，所以返回的是T参数类型的对象
        T vo = (T) voPrototype.getEmptyInstance();
        //看看读到了没有
        boolean exist = vo.readBy(bufferedReader);
        while (exist){
            //把读到的都加进去
            list.add(vo);
            vo = (T) voPrototype.getEmptyInstance();
            exist = vo.readBy(bufferedReader);
        }
        //关闭流
        try {
            bufferedReader.close();
            fileReader.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 保存list到文件，每次重写写入，不是追加
     * @param list
     */
    public void save(List<T> list){
        try {
            fileWriter = new FileWriter(file);
        }catch (Exception e){
            e.printStackTrace();
        }
        //调用每个元素 Vo 实现了Savable接口 的saveBy，让它把自己存进文件
        list.forEach(vo -> vo.saveBy(fileWriter));
        try {
            fileWriter.flush();
            fileWriter.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void close() throws IOException {
        bufferedReader.close();
        fileReader.close();
        fileWriter.close();
    }
}
